{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {
    "vscode": {
     "languageId": "raw"
    }
   },
   "source": [
    "---\n",
    "title: '`@nonmaterializable`'\n",
    "description: Declares that a type should exist only in the parameter domain.\n",
    "---"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can add the `@nonmaterializable` decorator on a struct to declare that the\n",
    "type can exist only in the parameter domain (it can be used for metaprogramming\n",
    "only, and not as a runtime type). And, if an instance of this type does\n",
    "transition into the runtime domain, this decorator declares what type it\n",
    "becomes there.\n",
    "\n",
    "To use it, declare your type with `@nonmaterializable(TargetType)`, where\n",
    "`TargetType` is the type that the object should convert to if it becomes a\n",
    "runtime value (you must declare the `TargetType`). For example, if a struct is\n",
    "marked as `@nonmaterializable(Foo)`, then anywhere that it goes from a\n",
    "parameter value to a runtime value, it automatically converts into the `Foo`\n",
    "type.\n",
    "\n",
    "For example, the following `NmStruct` type can be used in the parameter domain,\n",
    "but the `converted_to_has_bool` instance of it is converted to `HasBool` when it's\n",
    "materialized as a runtime value:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "@value\n",
    "@register_passable(\"trivial\")\n",
    "struct HasBool:\n",
    "    var x: Bool\n",
    "\n",
    "    fn __init__(inout self, x: Bool):\n",
    "        self.x = x\n",
    "\n",
    "    @always_inline(\"nodebug\")\n",
    "    fn __init__(inout self, nms: NmStruct):\n",
    "        self.x = True if (nms.x == 77) else False\n",
    "\n",
    "@value\n",
    "@nonmaterializable(HasBool)\n",
    "@register_passable(\"trivial\")\n",
    "struct NmStruct:\n",
    "    var x: Int\n",
    "\n",
    "    @always_inline(\"nodebug\")\n",
    "    fn __add__(self: Self, rhs: Self) -> Self:\n",
    "        return NmStruct(self.x + rhs.x)\n",
    "\n",
    "alias still_nm_struct = NmStruct(1) + NmStruct(2)\n",
    "# When materializing to a run-time variable, it is automatically converted,\n",
    "# even without a type annotation.\n",
    "var converted_to_has_bool = still_nm_struct"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ":::{.callout-note}\n",
    "\n",
    "**Note:** A non-materializable struct must have all of its methods annotated\n",
    "as `@always_inline`, and it must be computable in the parameter domain.\n",
    "\n",
    ":::"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<CommentService />"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Mojo",
   "language": "mojo",
   "name": "mojo-jupyter-kernel"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "mojo"
   },
   "file_extension": ".mojo",
   "mimetype": "text/x-mojo",
   "name": "mojo"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
